package test.serverframe.armc.server.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import org.codehaus.jackson.map.ObjectMapper;
import org.yaml.snakeyaml.Yaml;

import java.io.*;
import java.nio.charset.Charset;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * @Auther: lc
 * @Date: 2018/10/9 16:22
 * @Description:    配置管理中心-json工具类
 */
public class JsonUtil {

    /**
     * @desc: 将map转换为json
     * @param map 待转换的map
     * @return:
     * @auther: lc
     * @date: 2018/10/15 14:53
     */
    public static String mapToJson(Map map) throws IOException {
        ObjectMapper objectMapper=new ObjectMapper();
        String mapJson = objectMapper.writeValueAsString(map);
        return mapJson;
    }

    /**
     * @desc: properties文件转为json字符串
     * @param str   文件路径
     * @return:
     * @auther: lc
     * @date: 2018/10/15 14:54
     */
    public static String propertiesToJson(String str) throws IOException {
        //注释转义
        String tranStr = transferencePropertestStr(str);
        //字符串转为字节输入流
        InputStream inputStream = strToStream(tranStr);
        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
        String pair = "";
        //构造map
        Map<String,String> map = new LinkedHashMap<String,String>();
        while((pair=br.readLine())!=null){
            //读取key value
            String[] strings = pair.split("=");
            if (strings.length==2){
                map.put(strings[0], strings[1]);}
        }
        inputStream.close();
        br.close();
        String jsonStr = mapToJson(map);
        return jsonStr;
    }

    /**
     * jsonToYamlFile(含注释转义)
     * @param filePath 文件路径（不含文件名）
     * @param jsonString    json字符串
     * @param fileName      文件名
     * @return:
     * @auther: lc
     * @date: 2018/9/12 15:50
     */
    public static void jsonToYamlFile(String jsonString,String filePath,String fileName) throws JsonProcessingException, IOException {
        // 解析JSON 注释反转义
        jsonString = jsonString.replace("numsign", "#").replace("colon", ":");
        JsonNode jsonNodeTree = new com.fasterxml.jackson.databind.ObjectMapper().readTree(jsonString);
        // 存储为 YAML
        String jsonAsYaml = new YAMLMapper().writeValueAsString(jsonNodeTree);
        //截取前四个字符（ ---）
        jsonAsYaml = jsonAsYaml.substring(4).replace("\"", "");
        //写入到目标文件
        File dir=new File(filePath);
        if (!dir.exists()){
            dir.mkdir();
        }
        FileWriter writer = new FileWriter(filePath+"\\"+fileName);
        //注释反转义
        jsonAsYaml = jsonAsYaml.replace("note: ", "").replaceAll("note\\d+: ", "");
        writer.write(jsonAsYaml);
        writer.close();
    }

    /**
     * jsonToPropertiesFile(含注释转义)
     * @param filePath 文件路径（不含文件名）
     * @param jsonString    json字符串
     * @param fileName      文件名
     * @return:
     * @auther: lc
     * @date: 2018/9/27 10:02
     */
    public static void jsonToPropertiesFile(String jsonString,String filePath,String fileName) throws JsonProcessingException, IOException {
        // 解析JSON 注释反转义
        jsonString= jsonString.replace("numsign", "#").replace("colon", "=");
        //将json转换为map
        Map<String, Map<String, String>> map = JSON.parseObject(
                jsonString.trim(), LinkedHashMap.class, Feature.OrderedField);
        //写入目标文件
        File dir=new File(filePath);
        if (!dir.exists()){
            dir.mkdir();
        }
        BufferedWriter bufferedWriter=new BufferedWriter(new FileWriter(filePath+"\\"+fileName));
        //遍历map 注释反转义
        for (String key:map.keySet()){
            String record=key+"="+map.get(key);
            record=record.replaceAll("note\\d+=", "").replace("note=", "");
            System.out.println(record);
            bufferedWriter.write(record);
            bufferedWriter.newLine();
            bufferedWriter.flush();
        }
        bufferedWriter.close();
    }

    /**
     * yaml转json 带注释转义
     * @param str   yaml文件路径
     * @return:
     * @auther: lc
     * @date: 2018/9/12 15:24
     */
    public static String  yamlToJsonContainNote(String str) throws IOException {
        //注释转义
        String tranStr = transferenceYamlStr(str);
        //字符串转换为字节输入流
        InputStream inputStream = strToStream(tranStr);
        //字节输入流转换为json字符串
        String json = yamlToJson(inputStream);
        return json;
    }

    /**
     * @desc: yaml注释转义
     * @param str   待转义字符
     * @return:
     * @auther: lc
     * @date: 2018/10/15 15:08
     */
    public static String transferenceYamlStr(String str) throws IOException {
        StringBuffer sb=new StringBuffer(str);
        //转义单独为行的注释
        int temp=0;
        for (int i=0;i<sb.length()-1;i++){
            //如果当前字符为换行则截取之后的字符串
            if(sb.charAt(i)=='\n'){
                String s = sb.substring(i);
                //对于截取的字符串做循环判断，只循环一行
                for(int j=0;j<s.length()-1;j++){
                    //如果为‘#’开头，则为注释开始，做转移，并且退出循环
                    if(s.charAt(j)=='#'){
                        //为了让key不重复，用temp计数器
                        sb.replace(i+j,i+j+1,"note"+temp+++": #");
                        String s2 = sb.substring(i + j + 8);
                        break;
                    }
                    //如果为换行或者‘ ’则退出本次循环
                    else if(s.charAt(j)=='\n'||s.charAt(j)==' '){
                        continue;
                    }
                    //如果未为其他字符则退出循环
                    else {
                        break;
                    }
                }
            }
        }
        String s = sb.toString();
        //转义所有的#
        s = s.replaceAll("#","numsign");
        //转义注释在配置信息后中出现的‘：’，以及首行注释
        BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(s.getBytes(Charset.forName("utf8"))), Charset.forName("utf8")));
        String line;
        StringBuffer strbuf=new StringBuffer();
        temp=0;
        while ( (line = br.readLine()) != null ) {
            if(!"".equals(line.trim())){
                //转义首行注释
                if(temp==0){
                    line = line.replace("numsign", "note: numsign");
                }
                if(line.contains("numsign")){
                    String[] pves = line.split("numsig");
                    String pes=pves[1];
                    String pop = pes.replace(":", "colon");
                    line=pves[0]+"numsign"+pop;
                }
                temp++;
                strbuf.append(line+"\r\n");
            }
        }
        return strbuf.toString();
    }

    /**
     * @desc: properties转义注释
     * @param str   待转义字符
     * @return:
     * @auther: lc
     * @date: 2018/10/15 15:09
     */
    public static String transferencePropertestStr(String str) throws IOException {
        StringBuffer sb=new StringBuffer(str);
        //转义单独为行的注释
        int temp=0;
        for (int i=0;i<sb.length()-1;i++){
            //如果当前字符为换行则截取之后的字符串
            if(sb.charAt(i)=='\n'){
                String s = sb.substring(i);
                //对于截取的字符串做循环判断，只循环一行
                for(int j=0;j<s.length()-1;j++){
                    //如果为‘#’开头，则为注释开始，做转移，并且退出循环
                    if(s.charAt(j)=='#'){
                        //为了让key不重复，用temp计数器
                        sb.replace(i+j,i+j+1,"note"+temp+++"=#");
                        String s2 = sb.substring(i + j + 8);
                        break;
                    }
                    //如果为换行或者‘ ’则退出本次循环
                    else if(s.charAt(j)=='\n'||s.charAt(j)==' '){
                        continue;
                    }
                    //如果未为其他字符则退出循环
                    else {
                        break;
                    }
                }
            }
        }
        String s = sb.toString();
        //转义所有的#
        s = s.replaceAll("#","numsign");
        //转义注释在配置信息后中出现的‘=’，以及首行注释
        BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(s.getBytes(Charset.forName("utf8"))), Charset.forName("utf8")));
        String line;
        StringBuffer strbuf=new StringBuffer();
        temp=0;
        while ( (line = br.readLine()) != null ) {
            if(!"".equals(line.trim())){
                //转义首行注释
                if(temp==0){
                    line = line.replace("numsign", "note=numsign");
                }
                if(line.contains("numsign")){
                    String[] pves = line.split("numsig");
                    String pes=pves[1];
                    String pop = pes.replace("=", "colon");
                    line=pves[0]+"numsig"+pop;
                }
                temp++;
                strbuf.append(line+"\r\n");
            }
        }
        return strbuf.toString();
    }

    /**
     * @desc: str 转换为inputStream
     * @param str  待转换字符串
     * @return:
     * @auther: lc
     * @date: 2018/10/15 15:09
     */
    public static InputStream strToStream(String str){
        InputStream is = new ByteArrayInputStream(str.getBytes());
        return is;
    }

    /**
     * @desc:   yaml输入流转为json字符串
     * @param is   带转换输入流
     * @return:
     * @auther: lc
     * @date: 2018/10/15 15:10
     */
    public static String yamlToJson(InputStream is) throws IOException {
        Yaml yaml = new Yaml();//实例化解析器
        Map map = yaml.loadAs(is,LinkedHashMap.class);//装载的对象，这里使用LinkedHahMap（可以控制遍历顺序） 当然也可使用自己写的对象
        // Map breakMap = getBreakMap(map);
        String yamlJson = mapToJson(map);
        return yamlJson;
    }

    /**
     * @Descripttion 获取jsonArray （data不为list）
     * @Author LSY
     * @Date 16:45
     * @Param [ob]
     * @Return
     **/
    public static JSONArray getJSONArrayCtList(Object ob){
        String jsonStr = JSONObject.toJSONString(ob);
        JSONObject jsonObject= (JSONObject) JSON.parse(jsonStr);
        JSONObject data = jsonObject.getJSONObject("data");
        JSONArray jsonArray = (JSONArray) data.get("list");
        return  jsonArray;
    }

    /**
     * @Descripttion 获取jsonArray （data为list）
     * @Author LSY
     * @Date 16:45
     * @Param [ob]
     * @ReturngetJSONArray
     **/
    public static JSONArray getJSONArray(Object ob){
        String jsonStr = JSONObject.toJSONString(ob);
        JSONObject jsonObject= (JSONObject) JSON.parse(jsonStr);
        JSONArray jsonArray =(JSONArray) jsonObject.get("data");
        return  jsonArray;
    }
    /**
     * 给定出参和入参模型 返回入参的真实数据
     * @param inValue
     * @param outValue
     * @return
     */
    public static String convert(String outValue, String inValue){
        Object parse1 = JSON.parse(outValue);
        Map map1 = (Map) parse1;
        Map newMap = getNewMap(map1);
        Object parse2 = JSON.parse(inValue);
        Map map2 = (Map) parse2;
        reValue(newMap,map2);
        String outJSON = JSON.toJSONString(map2);
        return outJSON;
    }



    /**递归方法:
     * 当map2中的value为map1的key时,将map2中的value替换为map1中对应的value
     * @param map1
     * @param map2
     * @return
     */
    public static Map reValue(Map map1, Map  map2){
        for (Object key1:map1.keySet()){
            for (Object key2:map2.keySet()){
                if (map2.get(key2) instanceof  Map){
                    reValue(map1, (Map) map2.get(key2));
                }else {
                    if (key1.equals(map2.get(key2))){
                        map2.put(key2,map1.get(key1));

                    }
                }

            }

        }
        return map2;
    }


    /**
     * 将多级Map转换成key为AA.BB.CC的形式
     * @param key
     * @param map
     * @param newMap
     */
    public static void keyConvert(StringBuilder key, Map<String, Object> map, Map<String, Object> newMap) {
        Set<Map.Entry<String, Object>> entries = map.entrySet();
        for (Map.Entry entry : entries) {
            key.append(entry.getKey());
            Object value = entry.getValue();
            if (value instanceof Map) {
                key.append(".");
                keyConvert(key, (Map<String, Object>) value, newMap);
                key = new StringBuilder("");

            } else {
                newMap.put(key.toString(), value);
                if (!key.toString().contains(".")) {
                    key = new StringBuilder("");
                } else {
                    String substring = key.substring(0, key.lastIndexOf(".") + 1);
                    key = new StringBuilder(substring);
                }
            }
        }

    }

    public static Map getNewMap(Map<String, Object> map1) {
        Map newMap = new LinkedHashMap();
        keyConvert(new StringBuilder(""), map1, newMap);
        return newMap;
    }
    public static void main(String[] args) {

        //String outValue="{\"name\":\"BeJson\",\"url\":\"http://www.bejson.com\",\"page\":88,\"isNonProfit\":true,\"address\":{\"street\":\"科技园路.\",\"city\":\"江苏苏州\",\"country\":\"中国\"},\"links\":[{\"name\":\"Google\",\"url\":\"http://www.google.com\"},{\"name\":\"Baidu\",\"url\":\"http://www.baidu.com\"},{\"name\":\"SoSo\",\"url\":\"http://www.SoSo.com\"}]}";
        //String inValue="{\"name\":\"name\",\"url\":\"url\",\"page\":\"port\",\"isNonProfit\":\"isNonProfit\",\"address\":{\"street\":\"address.street\",\"city\":\"address.city\",\"country\":\"address.country\"}}";
    	String a = "{\"msg\":\"success\",\"data\":{\"expire\":43200,\"token\":\"2db584f1009df413b5942a766dc41c30\"},\"status\":0}";
		String b = "{\"token\":\"data.token\"}";

    	String outJSON= JsonUtil.convert(a,b);
        System.out.println(outJSON);

    }

}
